In general, Java language is compiled into intermediate language which is called as Java Virtual Machine Language (JVML) which can be interpreted by a Java Virtual Machine. The compiled result is called as a class file. The class file includes bytecodes.
Because the Java virtual machine bases on an stack operation, all operands are stored in a stack before they are used, and the operation result is also stored in the stack. As a result, the Java virtual machine can run Java application programs which are made up independently of the number of registers of an installed host processor.
Java programming language has a defective having a slow execution speed in comparison with a code that is made with language such as C or C++. However, to overcome this defective, Java programming language employs a software interpretation method, a JIT (Just-In-Time) compilation method, an AOT (Ahead-Of-Time) compilation method, or a hardware implementation method.
The software interpretation method is widely used in the case that restriction of resources is serious. However, because analysis of bytecodes is achieved in software, an execution speed of the analysis of bytecodes is slow. Further, the JIT complication method and the AOT complication method have shortcomings requiring a large capacity of memory, respectively.
The hardware implementation method achieves analysis of bytecodes in hardware unlike other methods, to thereby heighten the execution speed thereof. In addition, since the hardware implementation method does not need a large capacity of memory, it is suitable for an embedded system.
A software interpreter and a hardware interpreter are called commonly as a Java interpreter, respectively. The Java interpreter has native codes as codes that a Java virtual machine should execute for each bytecode. The Java interpreter executes bytecodes sequentially. If one bytecode is fetched, the Java interpreter decodes the fetched bytecode. Accordingly, the Java interpreter executes the bytecode with one or more native codes which perform the same operation as that of a corresponding bytecode. Here, since the hardware interpreter has a code to be executed in a memory beforehand, and then maps position of the code in hardware, the execution speed of the hardware interpreter is faster than that of the software interpreter where the mapping process is performed in software.
The bytecode is classified into an operation code (opcode) that prescribes an execution operation, and an operand which is dependent upon the operation code (opcode) and is used when a corresponding operation code (opcode) is executed. Since both the operation code (opcode) and the operand are made up of a single byte, respectively, the number of all possible operation codes (opcode) is totally 256. However, according to the Java virtual machine specification, the number of the operation codes (opcode) is prescribed into 202. The remaining operation codes (opcode) are prescribed so as to be defined and used as new bytecodes in the Java virtual machine. This may be defined by translating a corresponding operation code into a new operation code that is not defined in the Java virtual machine specification in the process of executing a particular bytecode. In addition, the operand may be translated into user's desired data.
If a Java application program is compiled, a class file is created in a manner that an operand is put at the back of each operation code and a subsequent operation code is put behind the operand. Here, each operation code may have several operands or may have no operand.
When Java application programs are executed, fields may be frequently accessed. In the case of bytecodes which are relevant with the field access, there are a static field access and an object field access. In each case, there are two kinds of bytecodes which perform writing and reading on and from a field. The bytecode for the static field access is defined as ‘getstatic’ and ‘putstatic,’ and the bytecode for the object field access is defined as ‘getfield’ and ‘putfield.’ These bytecodes for the static field access and the object field access have two operands, respectively.
FIG. 1 is a flowchart view illustrating a process of a conventional field access bytecode.
The process of processing the conventional field access bytecode as shown in FIG. 1, includes: a bytecode fetch step (S1); a field access determination step (S2); an execution step (S3); a field determination step (S4); a static field address detection step (S5); an object field address detection step (S6); an offset detection step (S7); a field address creation step (S8); and a data processing step (S9). The bytecode fetch step (S1) fetches bytecode from a class file. The field access determination step (S2) determines whether or not a bytecode that is fetched by an operation code of the bytecode that has been fetched from the bytecode fetch step (S1) is a bytecode for field access. If the bytecode that has been fetched in the field access determination step (S2) is not a bytecode for field access, the execution step (S3) jumps to a handler that corresponds to an operation code of a corresponding bytecode and executes the corresponding bytecode. If the bytecode that has been fetched in the field access determination step (S2) is a bytecode for field access, the field determination step (S4) determines whether or not the fetched bytecode is a bytecode for static field access that is getstatic or putstatic, or object field access that is getfield or putfield. If the bytecode that has been fetched in the field determination step (S4) is getstatic or putstatic, the static field address detection step (S5) extracts a static field address which is an initial address of the static field of a predetermined Java virtual machine. If the bytecode that has been fetched in the field determination step (S4) is getfield or putfield, the object field address detection step (S6) detects an object field address that is an initial address of an object field by object reference data stored in the top-level of a stack. The offset detection step (S7) analyzes a constant pool by an operand of the fetched bytecode and detects a field offset of an object to be accessed. The field address creation step (S8) adds the field offset detected in the offset detection step (S7) and the object field address or the static field address. The data processing step (S9) gains access to a field by the field address created in the field address creation step (S8), and processes data.
The data processing step (S9) stores data stored in the field of the corresponding field address in the top-level of a stack, if the fetched bytecode is getstatic or getfield. If the fetched bytecode is putstatic or putfield, the data processing step (S9) stores data stored just below the top-level of the stack in a field of a corresponding field address.
As illustrated in FIG. 1, in the case that the fetched bytecode is a bytecode relating to the field access, the offset detection step (S7) should analyze a constant pool necessarily and detect the field offset of an object to be accessed. In this case, since several thousands of native codes are usually required only in the case of a process of analyzing the constant pool, degradation occurs when executing Java application programs.
FIGS. 2 and 3 are flowchart views showing a conventional Java bytecode translating method that has been improved to prevent degradation at the time of executing Java application programs of FIG. 1, and FIG. 4 is a block diagram for explaining the getfield of an object field access in the conventional Java bytecode translating method of FIGS. 2 and 3.
The conventional Java bytecode translating method shown in FIGS. 2 to 4 has been proposed by SUN Microsystem company in order to reduce the number of native code in the case of the field access bytecode. Here, if the fetched bytecode is a bytecode for field access, the fetched bytecode is translated into a new bytecode and is processed as a bytecode for field access. For example, the new bytecode is ‘x_quick’ in which ‘x’ is one of getstatic, putstatic, getfield and putfield.
That is, as illustrated in FIG. 2, if a bytecode that is fetched in a specific program counter is a bytecode for field access (S11), a constant pool corresponding an operand of the bytecode is analyzed from the operand of the bytecode, in the same manner as that of the bytecode processing procedure for field access as illustrated in FIG. 1, and a field offset (FO) is detected by analysis of the constant pool, to thus process a field address (FA) and data (S13). Then, the field offset (FO) is stored at a position of the operand lb of the bytecode (S15), and an operation code (OP) of the bytecode is translated into ‘x_quick’ which is a new bytecode (S17). Here, as described above, ‘x’ is one of getstatic, putstatic, getfield and putfield. Thereafter, the translated operation code is recognized as ‘x_quick’ in the Java virtual machine.
As illustrated in FIGS. 3 and 4, the conventional Java bytecode translating method will follow.
The translated bytecode detection step (S20) detects whether or not the operation code (OP) 1a of the fetched bytecode 1 is ‘x_quick’ which is the operation code (OP) 1a of the bytecode for newly translated field access. If the bytecode detected in the translated bytecode detection step (S20) is a bytecode for newly translated field access, the field determination step (S30) determines whether or not the fetched bytecode is a bytecode for static field access or object field access. The static field address detection step (S40) extracts a static field address of a predetermined Java virtual machine if the bytecode fetched in the field determination step (S30) is the static field access, that is, getstatic_quick or putstatic_quick. The object field address detection step (S50) detects an object field address 5 by an object reference data (OD) stored in the top-level of a stack 3 if the bytecode fetched in the field determination step (S30) is the object field access, that is, getfield_quick or putfield_quick. The field address creation step (S60) adds the field offset (FO) that has been stored in the operand 1b of the fetched bytecode and the object field address or the static field address and creates a field address (FA). The data processing step (S70) gains access to a field 7 of the created field address (FA) and processes field data (FD).
The conventional Java bytecode translating method shown in FIGS. 2 to 4 does not need to perform an analysis of the constant pool for detecting the field offset in the case of the bytecode which has been translated into the new bytecode at the time of executing the bytecode for field access. Accordingly, the conventional Java bytecode translating method has an advantage of remarkably reducing the number of native codes. However, in the case of the bytecode for object field access, the conventional Java bytecode translating method has shortcomings that it should detect an object field address from object reference data located in the top-level of the stack, and should add the field offset (FO) that has been stored in the operand of the newly translated bytecode and the object field address or should add the field offset (FO) and the static field address, in order to create a field address. To perform these processes, a number of native codes are needed. For this reason, the conventional Java bytecode translating method has a problem that degradation still occurs at the time of execution of Java application programs.